'use strict'
const path = require('path')
const pkgDir = require('pkg-dir').sync
const pathExists = require('path-exists')
const npminstall = require('npminstall')
const fse = require('fs-extra')
const { isObject, getType } = require('@zy-cli/utils')
const formatPath = require('@zy-cli/format-path')
const { getDefaultRegistry, getNpmLatestVersion } = require('@zy-cli/get-npm-info')

class Package {
    constructor (options) {
        if (!options) {
            throw new Error('package类的options不能为空')
        }
        if (!isObject(options)) {
            throw new Error(`期望package类的参数为Object，但传入的是：${getType(options)}`)
        }
        // package 的目标路径
        this.targetPath = options.targetPath
        // package 的缓存路径
        this.storeDir = options.storeDir
        // package 的名称
        this.packageName = options.packageName
        // package 的版本
        this.packageVersion = options.packageVersion
        // package 缓存目录前缀
        this.cacheFilePathPrefix = this.packageName.replace(/\//g, '_')
    }

    async prepare() {
        if (this.storeDir && !pathExists(this.storeDir)) {
            fse.mkdirpSync(this.storeDir)
        }
        if (this.packageVersion === 'latest') {
            this.packageVersion = await getNpmLatestVersion(this.packageName)
        }
    }

    get cacheFilePath() {
        return path.resolve(this.storeDir, `_${this.cacheFilePathPrefix}@${this.packageVersion}@${this.packageName}`)
    }

    getSpecificCacheFilePath(packageVersion) {
        return path.resolve(this.storeDir, `_${this.cacheFilePathPrefix}@${packageVersion}@${this.packageName}`)
    }

    // 判断当前 Package 是否存在
    async exists() {
        if (this.storeDir) {
            await this.prepare()
            return pathExists(this.cacheFilePath)
        }
        return pathExists(this.targetPath)
    }

    // 安装 Package
    async install() {
        await this.prepare()
        return npminstall({
            root: this.targetPath,
            storeDir: this.storeDir,
            registry: getDefaultRegistry(),
            pkgs: [{
                name: this.packageName, 
                version: this.packageVersion 
            }]
        })
    }

    // 更新 Package
    async update() {
        await this.prepare()
        // 判断最新版本是否存在，如果存在则不安装，不存在才安装
        // 1. 获取最新 npm 模块版本号
        const latestVersion = await getNpmLatestVersion(this.packageName)
        // 2. 查询最新版本号对应的路径是否存在
        const latestFilePath = this.getSpecificCacheFilePath(latestVersion)
        // 3. 如果不存在则进行安装
        if (!pathExists(latestFilePath)) {
            await npminstall({
                root: this.targetPath,
                storeDir: this.storeDir,
                registry: getDefaultRegistry(),
                pkgs: [{ 
                    name: this.packageName, 
                    version: latestVersion 
                }]
            })
            this.packageVersion = latestVersion
        } else {
            this.packageVersion = latestVersion
        }
    }

    // 获取入口文件路径
    getRootFilePath() {
        function _getRootFile(targetPath) {
            // 1. 获取 package.json 的目录
            const dir = pkgDir(targetPath)
            if (dir) {
                // 2. 读取 package.json
                const pkgFile = require(path.resolve(dir, 'package.json'))
                // 3. 寻找 main/lib
                if (pkgFile && pkgFile.main) {
                    // 4. 路径的兼容（mac/windows）
                    return formatPath(path.resolve(dir, pkgFile.main))
                }
                return null
            }
            return null
        }
        if (this.storeDir) {
            return _getRootFile(this.cacheFilePath)
        }
        return _getRootFile(this.targetPath)
    }
}

module.exports = Package
